package com.yswy.common.exception;

import com.yswy.common.model.ResultModel;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.ValidationException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.RejectedExecutionException;


@RestControllerAdvice
@ResponseBody
@Slf4j
public class ApiExceptionHandler {
    private static final Logger logger = LoggerFactory.getLogger(ApiExceptionHandler.class);

    private static int DUPLICATE_KEY_CODE = 001;
    private static int PARAM_FAIL_CODE = 002;
    private static int VALIDATION_CODE = 003;

    @ExceptionHandler(Exception.class)
    public Object operateExp(HttpServletRequest request, HttpServletResponse response, Exception ex) {
        response.setCharacterEncoding("UTF-8");
        log.info("************-------异常信息：" + ex.getMessage() + new SimpleDateFormat("HH:mm:ss").format(new Date()), ex);
        if (ex instanceof NullPointerException || ex instanceof BusinessException) {
            return new ResultModel(500, ex.getMessage());
        } else if (ex instanceof BizException || ex instanceof IllegalStateException) {
            return new ResultModel(500, ex.getMessage());
        } else if (ex instanceof SignException) {
            return new ResultModel(-101, ex.getMessage());
        } else if (ex instanceof HttpRequestMethodNotSupportedException) {
            return new ResultModel(500, "请求异常");
        } else if (ex instanceof MissingServletRequestParameterException) {
            MissingServletRequestParameterException ex1 = (MissingServletRequestParameterException) ex;
            return new ResultModel(500, ex1.getParameterName() + "字段不能为空");
        } else if (ex instanceof ServletRequestBindingException) {
            String message = ex.getMessage();
            if (StringUtils.isNotBlank(message)) {
                message = message.substring(message.indexOf("'") + 1, message.lastIndexOf("'")) + "参数不能为空";
            }
            return new ResultModel(500, message);
        } else if (ex instanceof MethodArgumentTypeMismatchException) {
            String name = ((MethodArgumentTypeMismatchException) ex).getName();
            return new ResultModel(500, String.format("参数%s类型错误", name));
        } else if (ex instanceof MethodArgumentNotValidException) {
            BindingResult bindingResult = ((MethodArgumentNotValidException) ex).getBindingResult();
            String message = "";
            if (bindingResult.hasErrors()) {
                message = bindingResult.getAllErrors().get(0).getDefaultMessage();
            }
            return new ResultModel(500, message);
        } else if (ex instanceof BindException) {
            BindingResult bindingResult = ((BindException) ex).getBindingResult();
            String message = "";
            if (bindingResult.hasErrors()) {
                ObjectError objectError = bindingResult.getAllErrors().get(0);
                message = objectError.getDefaultMessage();
            }
            return new ResultModel(500, message);
        } else if (ex instanceof LoginException) {
            return new ResultModel(-1004, ex.getMessage());
        } else if (ex instanceof LookJlAdException) {
            return new ResultModel(-1002, ex.getMessage());
        } else if (ex instanceof WxLoginException) {
            return new ResultModel(-1003, ex.getMessage());
        } else if (ex instanceof NotPacketException) {
            return new ResultModel(-1001, ex.getMessage());
        } else if (ex instanceof RejectedExecutionException) {
            BindingResult bindingResult = ((BindException) ex).getBindingResult();
            String message = "";
            if (bindingResult.hasErrors()) {
                message = bindingResult.getAllErrors().get(0).getDefaultMessage();
            }
            return new ResultModel(500, message);
        } else if (ex instanceof IllegalArgumentException) {
            return ResultModel.error(ex.getMessage());
        } else if (ex instanceof BindException) {
            return ResultModel.error(ex.getMessage());
        } else if (ex instanceof ClockInException) {
            return new ResultModel(600, ex.getMessage());
        } else if (ex instanceof VipException) {
            return new ResultModel(700, ex.getMessage());
        } else {
            return new ResultModel(500, "服务器异常，请稍后再试");
        }
    }

    /**
     * 方法参数校验
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResultModel handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        logger.error(e.getMessage(), e);
        return new ResultModel(PARAM_FAIL_CODE, e.getBindingResult().getFieldError().getDefaultMessage());
    }

    /**
     * ValidationException
     */
    @ExceptionHandler(ValidationException.class)
    public ResultModel handleValidationException(ValidationException e) {
        logger.error(e.getMessage(), e);
        return new ResultModel(VALIDATION_CODE, e.getCause().getMessage());
    }

    @ExceptionHandler(DuplicateKeyException.class)
    public ResultModel handleDuplicateKeyException(DuplicateKeyException e) {
        logger.error(e.getMessage(), e);
        return new ResultModel(DUPLICATE_KEY_CODE, "数据重复");
    }

}
